package com.tangyuan.user.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.common.exception.BadRequestException;
import com.tangyuan.common.result.Result;
import com.tangyuan.common.result.ResultCodeEnum;
import com.tangyuan.common.util.BeanUtils;
import com.tangyuan.common.util.CollUtils;
import com.tangyuan.dto.CouponFormDTO;
import com.tangyuan.model.*;
import com.tangyuan.common.util.CommStatus;
import com.tangyuan.user.mapper.CouponExchangeCodeMapper;
import com.tangyuan.user.mapper.CouponMapper;
import com.tangyuan.user.service.CouponExchangeCodeService;
import com.tangyuan.user.service.CouponScopeService;
import com.tangyuan.user.service.CouponService;
import com.tangyuan.user.service.UserCouponService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 优惠券的规则信息 服务实现类
 * </p>
 *
 * @author Administrator
 */
@Service
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements CouponService {

    @Autowired
    private CouponService couponService;
    @Autowired
    private CouponExchangeCodeService codeService;
    @Autowired
    private UserCouponService userCouponService;

    @Autowired
    private CouponScopeService scopeService;


    @Override
    @Transactional
    public Result<Object> saveCoupon(CouponFormDTO dto) {
        // 1.保存优惠券
        // 1.1.转PO
        Coupon coupon = BeanUtils.copyBean(dto, Coupon.class);
        // 1.2.保存
        couponService.save(coupon);
        if (!dto.getSpecific()) {
            // 没有范围限定
            return Result.ok("操作成功！");
        }
        Long couponId = coupon.getId();
        // 2.保存限定范围
        List<Long> scopes = dto.getScopes();
        if (CollUtils.isEmpty(scopes)) {
            throw new BadRequestException("限定范围不能为空");
        }
        // 2.1.转换PO
        List<CouponScope> list = scopes.stream()
                .map(bizId -> new CouponScope().setBizId(bizId).setCouponId(couponId))
                .collect(Collectors.toList());
        // 2.2.保存
        scopeService.saveBatch(list);
        return Result.ok("操作成功！");
    }

    /**
     * 领取优惠券
     *
     * @param user
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Result<Object> beginIssue(User user, Long id) {
        // 1.查询优惠券
        Coupon coupon = getById(id);
        if (coupon == null) {
            return Result.build("",ResultCodeEnum.COUPON_NOT_EXIST);
        }
        LambdaQueryWrapper<CouponExchangeCode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CouponExchangeCode::getCouponId, coupon.getId());
        wrapper.eq(CouponExchangeCode::getUserId, user.getId());
        List<CouponExchangeCode> codeList = codeService.list(wrapper);
        if (!codeList.isEmpty()) {
            return Result.build("", ResultCodeEnum.COUPON_HAS_CLAIMED);
        }
        // 2.判断优惠券状态，是否是暂停或待发放
        if (coupon.getIssueBeginTime().before(new Date()) && coupon.getIssueEndTime().after(new Date())) {
            CouponExchangeCode code = new CouponExchangeCode();
            code.setCouponId(coupon.getId());
            code.setUserId(user.getId());
            String couponCode = CommStatus.getCode(7);
            code.setCode(couponCode);
            LocalDate localDate = LocalDate.now().plusDays(coupon.getTermDays());
            code.setExpiredTime(Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
            codeService.save(code);
            UserCoupon userCoupon = new UserCoupon();
            userCoupon.setUserId(user.getId());
            userCoupon.setCode(code.getCode());
            userCoupon.setCodeId(code.getId());
            userCoupon.setCouponId(coupon.getId());
            userCoupon.setTermBeginTime(new Date());
            userCoupon.setTermEndTime(code.getExpiredTime());
            userCouponService.save(userCoupon);
            return Result.ok(userCoupon);
        }
        return Result.build("",ResultCodeEnum.COUPON_NOT_REQUIREMENTS);
    }

    @Override
    public Result<Object> writeOffCoupon(Long userId, String code) {
        // 参数校验
        if (userId == null || code == null || code.trim().isEmpty()) {
            return Result.build(null,ResultCodeEnum.ARGUMENT_VALID_ERROR);
        }

        LambdaQueryWrapper<UserCoupon> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCoupon::getCode, code);
        UserCoupon userCoupon = userCouponService.getOne(wrapper);

        // 查询代金券，确保其存在且未被使用
        if (userCoupon == null ) {
            return Result.build(null,ResultCodeEnum.COUPON_NOT_EXIST);
        }
        if (userCoupon.getStatus() == 2) {
            return Result.build(null,ResultCodeEnum.COUPON_HAS_USED);
        }
        //优惠卷过期
        if (userCoupon.getTermEndTime().before(new Date())){
            userCoupon.setUsedTime(new Date());
            userCoupon.setStatus(3);
            userCouponService.updateById(userCoupon);

            LambdaUpdateWrapper<CouponExchangeCode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.set(CouponExchangeCode::getStatus, 3);
            lambdaUpdateWrapper.set(CouponExchangeCode::getUpdateTime, new Date());
            lambdaUpdateWrapper.eq(CouponExchangeCode::getCode, code);
            lambdaUpdateWrapper.eq(CouponExchangeCode::getUserId, userId);
            codeService.update(lambdaUpdateWrapper);

            return Result.build(null,ResultCodeEnum.ACTIVE_OVER_TIME);
        }
        userCoupon.setUsedTime(new Date());
        userCoupon.setStatus(2);
        userCouponService.updateById(userCoupon);

        LambdaUpdateWrapper<CouponExchangeCode> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(CouponExchangeCode::getStatus, 2);
        lambdaUpdateWrapper.set(CouponExchangeCode::getUpdateTime, new Date());
        lambdaUpdateWrapper.eq(CouponExchangeCode::getCode, code);
        codeService.update(lambdaUpdateWrapper);

        return Result.ok("操作成功！");
    }
}
